﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace DcsGauges.Shared.DataStructures
{
    public class DcsProperty
    {
        public int Property { get; private set; }
        public string Name { get; private set; }

        public DcsProperty(string propertyName)
        {
            this.Property       = DcsProperties.PropertyId(propertyName);
            this.Name           = propertyName;
        }

        public DcsProperty(int propertyConstant)
        {
            this.Property       = propertyConstant;
            this.Name           = DcsProperties.PropertyName(this.Property);
        }

        public static implicit operator DcsProperty(int propertyConstant)
        {
            return new DcsProperty(propertyConstant);
        }


        public static implicit operator int(DcsProperty property)
        {
            return property.Property;
        }

        public override bool Equals(object obj)
        {
            var typed = obj as DcsProperty;

            if (typed == null)
            {
                return false;
            }

            return this.Property == typed.Property;
        }

        public bool Equals(DcsProperty prop)
        {
            if (prop == null)
            {
                return false;
            }

            return this.Property == prop.Property;
        }

        public override int GetHashCode()
        {
            return this.Property;
        }
    }

    public static class DcsProperties
    {
        private static Dictionary<int, string>          idToNameMap                 = new Dictionary<int,string>();
        private static Dictionary<string, int>          nameToIdMap                 = new Dictionary<string,int>();

        /* DCS-A10 Properties */

        public static IEnumerable<int>          AllProperties           { get { return idToNameMap.Keys; }}

        internal static string PropertyName(int property)
        {
            return idToNameMap[property]; 
        }

        internal static int PropertyId(string property)
        {
            return nameToIdMap[property];
        }

        static DcsProperties()
        {
            Init();
        }

        private static void Init()
        {
            Type t = typeof(DcsProperties);
            ProcessCurrentType(t, "DCS");
        }
        
        private static void ProcessCurrentType(Type currentClass, string parentName)
        {
            FieldInfo[] fields = currentClass.GetFields();
            foreach (var f in fields)
            {
                if(f.FieldType == typeof(int))
                {
                    string fieldName        = f.Name;
                    int value               = (int)f.GetValue(f);
                    idToNameMap.Add(value, parentName + "." + fieldName);
                    nameToIdMap.Add(parentName + "." + fieldName, value);
                }
            }

            Type[] nestedTypes = currentClass.GetNestedTypes();
            foreach (var nt in nestedTypes)
            {
                ProcessCurrentType(nt, parentName + "." + nt.Name);
            }
        }

        public const int Unknown                                            = 0;

        public static class Engines
        {
            public static class Left
            {
                public static class Temperature
                {
                    public const int            Units                       = 70;
                    public const int            Tenth                       = 71;
                }

                public static class CoreSpeed
                {
                    public const int            Units                       = 78;
                    public const int            Tenth                       = 79;
                }

                public const int                OilPressure                 = 82;
                public const int                FanSpeed                    = 76;
                public const int                FuelFlow                    = 84;
            }

            public static class Right
            {
                public static class Temperature
                {
                    public const int            Units                       = 73;
                    public const int            Tenth                       = 74;
                }

                public static class CoreSpeed
                {
                    public const int            Units                       = 80;
                    public const int            Tenth                       = 81;
                }

                public const int                OilPressure                 = 83;
                public const int                FanSpeed                    = 77;
                public const int                FuelFlow                    = 85;            
            }
        }

        public static class Panels
        {
            public static class Right
            {
                public static class Oxygen
                {
                    public const int            FlowIndicator               = 600;
                    public const int            EmergencyLever              = 601;
                    public const int            Regulator                   = 602;
                    public const int            Supply                      = 603;
                    public const int            Pressure                    = 604;  
                }

                public static class Environment
                {
                    public const int            WindShieldDefog             = 276;
                    public const int            CanopyDefog                 = 277;
                    public const int            PitotHeat                   = 279;
                    public const int            BleedAir                    = 280;
                    public const int            CabinPressure               = 281;
                    public const int            TemperaturePressure         = 282;
                    public const int            MainAirSupply               = 283;
                    public const int            FlowLevelControl            = 284;
                    public const int            CabinAirOperator            = 285;
                    public const int            TemperatureLevel            = 286;
                }

                public static class LightControl
                {
                    public const int            PositionFlash               = 287;
                    public const int            Formation                   = 288;
                    public const int            AntiCollision               = 289;
                    public const int            EngineInstruments           = 290;
                    public const int            NoseIllumination            = 291;
                    public const int            FlightInstruments           = 292;
                    public const int            AuxiliaryInstruments        = 293;
                    public const int            SignalLights                = 294;
                    public const int            AccelAndComp                = 295;
                    public const int            Flood                       = 296;
                    public const int            Console                     = 297;
                }           

                public static class Caution
                {
                    public const int            EngineStartCycle            = 480;
                    public const int            HydraulicPressLeft          = 481;
                    public const int            HydraulicPressRight         = 482;
                    public const int            GunUnsafe                   = 483;
                    public const int            AntiSkid                    = 484;
                    public const int            HydraulicResLeft            = 485;
                    public const int            HydraulicResRight           = 486;
                    public const int            OxygenLow                   = 487;
                    public const int            ElevationDisengage          = 488;
                    public const int            Space1                      = 489;
                    public const int            SeatNotArmed                = 490;
                    public const int            BleedAirLeak                = 491;
                    public const int            AilDisengage                = 492;
                    public const int            AilTabLeft                  = 493;
                    public const int            AilTabRight                 = 494;
                    public const int            ServiceAirHot               = 495;
                    public const int            PitchSas                    = 496;
                    public const int            EngineHotLeft               = 497;
                    public const int            EngineHotRight              = 498;
                    public const int            WindShieldHot               = 499;
                    public const int            YawSas                      = 500;
                    public const int            EngineOilPressLeft          = 501;
                    public const int            EngineOilPressRight         = 502;
                    public const int            Cicu                        = 503;
                    public const int            Gcas                        = 504;
                    public const int            MainPumpLeft                = 505;
                    public const int            Space2                      = 507;
                    public const int            MainPumpRight               = 506;
                    public const int            Laste                       = 508;
                    public const int            WingPumpLeft                = 509;
                    public const int            WingPumpRight               = 510;
                    public const int            Hars                        = 511;
                    public const int            IffMode4                    = 512;
                    public const int            MainFuelLowLeft             = 513;
                    public const int            MainFuelLowRight            = 514;
                    public const int            LeftRightTanksUnequal       = 515;
                    public const int            Eac                         = 516;
                    public const int            FuelPressLeft               = 517;
                    public const int            FuelPressRight              = 518;
                    public const int            Nav                         = 519;
                    public const int            StallSystem                 = 520;
                    public const int            ConvLeft                    = 521;
                    public const int            ConvRight                   = 522;
                    public const int            Cadc                        = 523;
                    public const int            ApuGen                      = 524;
                    public const int            GeneratorLeft               = 525;
                    public const int            GeneratorRight              = 526;
                    public const int            InstInverter                = 527;
                }
            }
        }

        public static class FuelQuantity
        {
            public const int                    Left                        = 88;
            public const int                    Right                       = 89;
            public const int                    FuelQuantityDigital10000    = 90;
            public const int                    FuelQuantityDigital1000     = 91;
            public const int                    FuleQuantityDigital100      = 92;
        }

        public static class Cockpit //holds values of the 'simple gauges' (gauges that have only one value or where grouping is not reall usefull)
        {
            public const int                    AngleOfAttack               = 4;
            public const int                    MagneticCompass             = 6;
            public const int                    FlapsPositionIndicator      = 7;
            public const int                    VerticalVelocityIndicator   = 12;
            public const int                    ApuTachometer               = 13;
            public const int                    ApuTemperature              = 14;
            public const int                    Accelerometer               = 15;
            public const int                    AzimuthIndicator            = 16;
        }

        public static class AttitudeDirectionIndicator
        {
            public static class Sphere
            {
                public const int                Pitch                       = 17;
                public const int                Roll                        = 18;
            }

            public static class Bars
            {
                public const int                Pitch                       = 20;
                public const int                Roll                        = 21;
            }
        }

        public static class HoriziontalSituationIndicator
        {
            public static class Range
            {
                public const int                Digital10000                = 28;
                public const int                Digital1000                 = 29;
                public const int                Digital100                  = 30;
                public const int                Digital10                   = 31;
            }

            public static class CourseSelector
            {
                public const int                Digital100                  = 37;
                public const int                Digital1                    = 39;
            }   

            public const int                    Compass                     = 34;
            public const int                    Bearing1                    = 33;
            public const int                    Bearing2                    = 35;
            public const int                    HeadingMarker               = 36;
            public const int                    PowerOffWarning             = 40;
            public const int                    CourseDeviation             = 41; 
            public const int                    CourseArrow                 = 47;

            
        }     
  
#warning this values are taken from Cuaton Light Panel -> check if these are also used to trigger the corresponding control!!!
        public static class ElectricalPanel
        {
            public const int                    ApuGenerator                = 241;
            public const int                    Inverter                    = 242;
            public const int                    EmergencyFlood              = 243;
            public const int                    BatteryPower                = 246;

            public static class AcPowerGen
            {
                public const int                Left                        = 244;
                public const int                Right                       = 245;
            }
        }

    }
}
